#include "goldelox.h"


goldelox::goldelox()
{

}

byte goldelox::CMD(char* c,int n) {
      int i=0;
      _serial->flush();
      byte b;
#ifdef GOLDELOX_DEBUG
      Serial.print("CMD:");
      for (i=0;i<n;i++) {
      	  Serial.print(c[i],HEX);
	  Serial.print(" ");
      }	
      Serial.println();
#endif
      for (i=0;i<n;i++) {
          _serial->print(c[i]);    
      }	
      while (! _serial->available() ) delayMicroseconds(50);      
       b= _serial->read();
#ifdef GOLDELOX_DEBUG
      Serial.print("RES:");
      Serial.print(b,HEX);
#endif
      return b;          
}


void goldelox::powerON()
{
	char cmd[]={0x59,0x01,0x01,'\n'};
	CMD(cmd,3);
}

void goldelox::powerOFF()
{
	char cmd[]={0x59,0x01,0x00,'\n'};
	CMD(cmd,3);
}

void goldelox::lowPower()
{
	char cmd[]={0x59,0x03,0x00,'\n'};
	CMD(cmd,3);
}

void goldelox::normalPower()
{
	char cmd[]={0x59,0x03,0x01,'\n'};
	CMD(cmd,3);
}

void goldelox::sleep()
{
	char cmd[]={0x5A,0x01,'\n'};
	CMD(cmd,2);
}

void goldelox::version()
{
	char cmd_ver[]={0x56,0x01,'\n'};
	CMD(cmd_ver,2);
}

void goldelox::clear()
{
	char cmd_clear[]={0x45,'\n'};
	CMD(cmd_clear,1);
}

void goldelox::black()
{
	char cmd_black[]={0x42,0x00,0x00,'\n'};
	CMD(cmd_black,3);
}

void  goldelox::putPixel(int x, int y, int color)
{
      char cmd[5];
      cmd[0]=0x50;       
      cmd[1]= x;
      cmd[2]= y;
      cmd[3]= (color>>8) ;
      cmd[4]= (color) ;
      CMD(cmd,5);
}

void goldelox::penSolid()
{
	char cmd_pen_solid[]={0x70,0x00,'\n'};
	CMD(cmd_pen_solid,2);
}

void goldelox::penWire()
{
	char cmd_pen_wire[]={0x70,0x01,'\n'};
	CMD(cmd_pen_wire,2);
}

// Get 16bits value from RGB (0 to 63, 565 format)
int goldelox::getRGB(int red, int green, int blue)
{
	int outR = ((red * 31) / 255);
	int outG = ((green * 63) / 255);
	int outB = ((blue * 31) / 255);

	return (outR << 11) | (outG << 5) | outB;
}

void goldelox::opaqueText()
{
	char cmd_text_opaque[]={0x4F,0x01,'\n'};
        CMD(cmd_text_opaque,2);
}

void goldelox::transparentText()
{
	char cmd_text_transparent[]={0x4F,0x00,'\n'};
            CMD(cmd_text_transparent,2);
}

void goldelox::text(int x,int y,int v,int color) {
        sprintf(buffer,"%+i\n",v);
	text(x,y,buffer,color,1);
}

void goldelox::text(int x,int y,uint16_t v,int color) {
        sprintf(buffer,"%u\n",v);
	text(x,y,buffer,color,1);
}

void goldelox::text(int x,int y,uint32_t v,int color) {
        sprintf(buffer,"%u\n",v);
	text(x,y,buffer,color,1);
}


void goldelox::text(int x,int y,float v,int color) {
	  sprintf(buffer,"%+4i",(int)v);
	  int temp = (v - (int)v)*10;
	  sprintf(&buffer[4],".%1i\n",abs(temp));
	  text(x,y,buffer,color,1);
}

void goldelox::text(int x,int y,char* c,int color) {
	text(x,y,c,color,1);
}

void goldelox::text(int x,int y,char* c,int color,int scale) {
       int size=0,i=0;

       while (c[size]!='\n' & c[size]!=0x0) {
         size++;
      }

       char cmd[8+size+1];
       cmd[0]=0x53;
       cmd[1]= x;
       cmd[2]= y;       
       cmd[3]=0x10;
       cmd[4]= (color >>8) ;
       cmd[5]= color;
       cmd[6]= scale;
       cmd[7]= scale;
       for (i=0;i<size;i++){
         cmd[i+8]=c[i];
       }
       cmd[8+size]=0x00;
       CMD(cmd,8+size+1);
}
#ifdef SOFTSERIAL
void goldelox::init(NewSoftSerial *serial) {
	_serial=serial;
	_serial->begin(57600);  
	init2();
}
#else
void goldelox::init(HardwareSerial *serial) {
	_serial=serial;
	_serial->begin(115200);  
	init2();
}
#endif

void goldelox::init2()
{
  char a=0x15;
  delay(600);
  while (a!=0x06) {
    _serial->flush();
    _serial->print('U');
    while (!_serial->available() ) {
	    delayMicroseconds(50);
    }
    a=_serial->read();
#ifdef GOLDELOX_DEBUG
    Serial.println("baudrate...");
    Serial.println(a,HEX);
#endif
  }
  black();
  clear();

//  version();
  about(); 
  delay(1000);
}

void goldelox::sound(int f,int d)
{
  char cmd[5];
  cmd[0]=0x4E;  
  cmd[1]= (f>>8);
  cmd[2]= f;
  cmd[3]= (d>>8);
  cmd[4]= d;
  CMD(cmd,5);
}

void goldelox::setSDpointer(unsigned long address)
{
  char cmd[6];
  cmd[0]=0x40;
  cmd[1]=0x41;
  cmd[2]= (address>>24);
  cmd[3]= (address>>16);
  cmd[4]= (address>>8);
  cmd[5]= address;
  while (CMD(cmd,6)==0x15) delayMicroseconds(50);   
}


byte  goldelox::readByte() {
        byte b;
	char cmd[]={0x40,0x72,'\n'};
        return CMD(cmd,2);
}

byte goldelox::readByte(unsigned long address)
{

	static unsigned long old_address=-10;
	if (old_address+1 != address) {
		setSDpointer(address);
        }
      	old_address = address;
	return readByte();
}

void goldelox::writeByte(unsigned long address,byte byte)
{

}

void  goldelox::imageToSD(int x,int y, int width,int height,unsigned long address)
{
      char cmd[9];       
      cmd[0]= 0x40;
      cmd[1]= 0x43;
      cmd[2]= x;
      cmd[3]= y;
      cmd[4]= width;	
      cmd[5]=height;
      cmd[6]= (address>>16) ;
      cmd[7]= (address>>8) ;
      cmd[8]= address ;
      CMD(cmd,9);
}

void  goldelox::showVideo(int x,int y, int width,int height,int frames,unsigned long address) {
//      char cmd[]={0x40,0x56,0x0,0x0,128,128,0x10,0x50,0x0,0x0,0x0,0x0,0x0,'\n'};
      char cmd[13];              
      cmd[0]= 0x40;
      cmd[1]= 0x56;
      cmd[2]= x;
      cmd[3]= y;
      cmd[4]= width;	
      cmd[5]= height;
      cmd[6]=0x10;
      cmd[7]=0x50;
      cmd[8]= (frames>>8);     	
      cmd[9]= (frames);     	
      cmd[10]= (address>>16) ;
      cmd[11]= (address>>8) ;
      cmd[12]= address ;
      CMD(cmd,13);
}

void  goldelox::showVideo(int frames,unsigned long address)
{
      showVideo(0,0,128,128,frames,address);
}

void goldelox::showImage(int x,int y,int width,int height,unsigned long address)
{
//      char cmd[]={0x40,0x49,0x0,0x0,128,128,0x10,0x0,0x0,0x0,'\n'};       
      char cmd[10];
      cmd[0]= 0x40;
      cmd[1]= 0x49;
      cmd[2]= x;
      cmd[3]= y;
      cmd[4]= width;	
      cmd[5]= height;
      cmd[6]= 0x10;
      cmd[7]= (address>>16) ;
      cmd[8]= (address>>8) ;
      cmd[9]= address ;
      CMD(cmd,10);
}

void  goldelox::showImage(unsigned long n) {
      unsigned long j;
      j=64*n;
      showImage(0,0,128,128,j);
}

void goldelox::copyPaste(int x0,int y0, int x1,int y1,int width,int height)
{
//     char cmd[]={0x63,0x0,0x0,0x0,0x0,128,128,'\n'};       
      char cmd[7];
      cmd[0]= 0x63;
      cmd[1]= x0;
      cmd[2]= y0;
      cmd[3]= x1;
      cmd[4]= y1;
      cmd[5]= width;	
      cmd[6]= height;
      CMD(cmd,7);
}

void goldelox::cutPaste(int x0,int y0, int x1,int y1,int width,int height)
{
	copyPaste(x0,y0, x1,y1,width,height);
	penSolid();
	rectangle(x0,y0,x0+width,y0+height,0x00);
}

void goldelox::changeColor(int x0,int y0, int x1,int y1,int color,int to_color) {
//     char cmd[]={0x72,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,'\n'};
     char cmd[9];
     cmd[0]= 0x72; //OJO ESTA MAL!
     cmd[1]= x0;
     cmd[2]= y0;
     cmd[3]= x1;
     cmd[4]= y1;
     cmd[5]= (to_color >>8);
     cmd[6]= (to_color);
     cmd[7]= (color >>8);
     cmd[8]= color;
     CMD(cmd,9);
}


void goldelox::rectangle(int x0,int y0, int x1,int y1,int color) {
//     char cmd[]={0x72,0x00,0x00,0x00,0x00,0xFF,0xFF,'\n'};
     char cmd[7];
     cmd[0]= 0x72;
     cmd[1]= x0;
     cmd[2]= y0;
     cmd[3]= x1;
     cmd[4]= y1;
     cmd[5]= (color >>8);
     cmd[6]= color;
     CMD(cmd,7);
}

void goldelox::line(int x0,int y0, int x1,int y1,int color) {
//     char cmd[]={0x4C,0x00,0x00,0x00,0x00,0xFF,0xFF,'\n'};
     char cmd[7];
     cmd[0]=0x4C;
     cmd[1]=x0;
     cmd[2]=y0;
     cmd[3]=x1;
     cmd[4]=y1;
     cmd[5]=color >>8;
     cmd[6]=color;
     CMD(cmd,7);
}

void goldelox::circle(int x,int y, int r,int color) {
//     char cmd[]={0x43,0x28,0x32,0x0B,0x00,0x1F,'\n'};
     char cmd[6];
     cmd[0]=0x43;
     cmd[1]=x;
     cmd[2]=y;
     cmd[3]=r;
     cmd[4]=color >>8;
     cmd[5]=color;
     CMD(cmd,6);
}

void goldelox::polygon(int vertices,char v[],int color) {
     int size,j;
     size=1+1+vertices*2+2+1;
     char cmd[size];
     cmd[0]=0x67;
     cmd[1]=vertices;
     for (j=1;j<=vertices;j++){
     cmd[j*2]=v[j*2-2];
     cmd[j*2+1]=v[j*2-1];       
     }  
     cmd[size-3]=color >>8;
     cmd[size-2]=color;
     cmd[size-1]='\n';
     CMD(cmd,size-1);
}

void goldelox::arrow(int t) {
      int a,b,c,d;
      int x,y;
      a=20;
      b=25;
      c=10;
      d=5;
      char v[7*2];
      switch (t) {
        case 0:
          x=64;
          y=0;
          v[0]=x;
          v[1]=y;
          v[2]=x+a/2;
          v[3]=y+c;
          v[4]=x+a/2-d;
          v[5]=y+c;
          v[6]=x+a/2-d;
          v[7]=y+b;
          v[8]=x-a/2+d;
          v[9]=y+b;
          v[10]=x-a/2+d;
          v[11]=y+c;
          v[12]=x-a/2;
          v[13]=y+c;
          break;
          
        case 1:
          x=128;
          y=64;
          v[0]=x;
          v[1]=y;
          v[2]=x-c;
          v[3]=y+a/2;
          v[4]=x-c;
          v[5]=y+a/2-d;
          v[6]=x-b;
          v[7]=y+a/2-d;
          v[8]=x-b;
          v[9]=y-a/2+d;
          v[10]=x-c;
          v[11]=y-a/2+d;
          v[12]=x-c;
          v[13]=y-a/2;
          break;
          
        case 2:
          x=64;
          y=128;
          v[0]=x;
          v[1]=y;
          v[2]=x+a/2;
          v[3]=y-c;
          v[4]=x+a/2-d;
          v[5]=y-c;
          v[6]=x+a/2-d;
          v[7]=y-b;
          v[8]=x-a/2+d;
          v[9]=y-b;
          v[10]=x-a/2+d;
          v[11]=y-c;
          v[12]=x-a/2;
          v[13]=y-c;
          break;
          
       case 3:
          x=0;
          y=64;
          v[0]=x;
          v[1]=y;
          v[2]=x+c;
          v[3]=y+a/2;
          v[4]=x+c;
          v[5]=y+a/2-d;
          v[6]=x+b;
          v[7]=y+a/2-d;
          v[8]=x+b;
          v[9]=y-a/2+d;
          v[10]=x+c;
          v[11]=y-a/2+d;
          v[12]=x+c;
          v[13]=y-a/2;
          break;

      }
      penWire();
      polygon(7,v,0xFA00);

}



void goldelox::about() {
  penWire();
  transparentText();
  showImage(30);
  rectangle(20,20,108,108,getRGB(0,0,0));
  rectangle(18,18,110,110,0xFA00);
  text(50,22,"ALICE\n",0xA000);
  text(25,42,"Advanced Live\n",0xF200);
  text(35,52,"Inspector\n",0xF200);
  text(23,62,"Cosmo Explorer\n",0xF200);
  text(55,98,"0.1",getRGB(0,0,63));
  text(50,115,"Nacho+\n",0xA0AF);
}

void goldelox::test0() {
  /* test de animación*/
  static int i=0,j=0;
  showImage(j);
  arrow(i);
  if (i<3) {
  i++;
  } else {
      i=0;
      if (j<80) {
        j++;
      } else {
        j=0;
      }
  }
}

void goldelox::nivel(int an) { 
  int size=50,x0,y0,x1,y1;
  float angle;
  float pi=3.14159265;
  static int old_an;
  if (an==old_an) return;
  old_an=an;
  angle=(float)an*pi/180.0;
  //showImage(0); 
  clear();
  //changeColor(0,0,128,128,0xFA00,0x0000);
  //rectangle(0,0,128,128,0x00);
  x0=size*sin(angle)+64;
  y0=size*cos(angle)+64;
  x1=64-size*sin(angle);
  y1=64-size*cos(angle);
  line(x0,y0,x1,y1,0xFA00);
  sprintf(buffer,"%u\n",an);
  text(64,120,buffer,0xFA00,1);
  if (an<90) arrow(0);
}

void goldelox::test1() {
static int i=0;
int   static a=4;
nivel(i);
i=i+a;
if (i>180) a=-4;
if (i<0) a=4;  
}



void goldelox::testReadByte()
{
  int o=0;
  byte b;
  clear();
  opaqueText(); 
  text(10,10,"SD reading Test" ,0xA0AF);
  int i;
  for(i=1;i<512;i++){
  b=readByte(i);
  sprintf(buffer,"byte:%u/%u %#x   \n",i,512*4,b);
  text(10,85,buffer,0xA0AF);
  //delay(50);
  }
}


void goldelox::testCopyPaste()
{
float i=0;
showImage(0);
imageToSD(60,60,20,20,0x00FFFF);
clear();
//showImage(20,20,20,20,0x00FFFF);
penSolid();
for (i=0;i<60;i+=0.1){
	showImage(20*sin(i)+64,20*cos(i)+64,20,20,0x00FFFF);

	rectangle(20*sin(i)+64,20*cos(i)+64,20*sin(i)+64+20,20*cos(i)+64+20,0x00);

}
}



goldeloxPlus::goldeloxPlus():goldelox()
{

}

void goldeloxPlus::thermo(int x,int y,int color,int size,float T)
{
  sprintf(buffer,"%+2i",(int)T);
  int temp = (T - (int)T)*10;
  sprintf(&buffer[3],".%1i C\n",abs(temp));
  text(x,y,buffer,color,size);
}

void goldeloxPlus::showDate(int x,int y,int color)
{
  sprintf(buffer,"%02i/%02i/%04i\n",day(),month(),year());
  text(x,y,buffer,color,1);
}

void goldeloxPlus::showTime(int x,int y,int color)
{
  sprintf(buffer,"%02i:%02i:%02i\n",hour(),minute(),second());
  text(x,y,buffer,color,1);
}

void goldeloxPlus::showClock()
{
	int c=getRGB(0,40,0);
  	showDate(65,0,c);
	showTime(0,0,c);
}

void goldeloxPlus::showHHMMSS(int x,int y,float a,int color)
{
  int sig=1;
  if (a<0) {
	sig=-1;
  } 
  int s=abs(a)*3600;	
  int hh=(int) abs(a);
  int mm=(int)((s-hh*3600)/60);
  int ss=s-hh*3600-mm*60; 
  sprintf(buffer,"%+02i:%02i:%02i\n",sig*hh,mm,ss);
  text(x,y,buffer,color,1);
}




